// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
//
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.ui.query;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.dengues.commons.IDenguesSharedImage;
import org.dengues.commons.utils.ImageUtil;
import org.dengues.core.metadata.types.MetadataTypesManager;
import org.dengues.core.resource.DenguesProject;
import org.dengues.core.scripts.ScriptVariable;
import org.dengues.model.DenguesModelManager;
import org.dengues.model.database.DBColumn;
import org.dengues.model.database.DBTable;
import org.dengues.model.database.DatabaseDiagram;
import org.dengues.model.database.DatabaseFactory;
import org.dengues.model.database.DiagramChild;
import org.dengues.model.database.EMFDataType;
import org.dengues.model.database.ForeignKey;
import org.dengues.model.project.ConnPropertySetType;
import org.dengues.ui.prefs.connectivity.EConnectivityProperties;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * $Id: Dengues.epf 2007-12-12 qiang.zhang $
 * 
 */
public final class QueryUiUtils {

    /**
     * 
     */
    private static final String SCRIPTS_COMMENT = "SCRIPTS_COMMENT";

    private static QueryUiUtils instance = null;

    /**
     * Qiang.Zhang.Adolf@gmail.com QueryUiUtils constructor comment.
     */
    private QueryUiUtils() {
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getInstance".
     * 
     * @return
     */
    public static QueryUiUtils getInstance() {
        if (instance == null) {
            instance = new QueryUiUtils();
        }
        return instance;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createDbDiagramTree".
     * 
     * @param leftComp
     * @param dbDiagram2
     * @return
     */
    public TreeViewer createDbDiagramTree(Composite leftComp, DatabaseDiagram dbDiagram2) {
        GridData gridData;
        TreeViewer viewer = new TreeViewer(leftComp, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
        gridData = new GridData(GridData.FILL_BOTH);
        viewer.getTree().setLayoutData(gridData);
        ColumnsTreeProvider provider = new ColumnsTreeProvider();
        viewer.setContentProvider(provider);
        viewer.setLabelProvider(provider);
        viewer.setInput(dbDiagram2);
        viewer.expandAll();
        return viewer;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createDbDiagramCheckBoxTree".
     * 
     * @param leftComp
     * @param dbDiagram2
     * @return
     */
    public CheckboxTreeViewer createDbDiagramCheckBoxTree(Composite leftComp, DatabaseDiagram dbDiagram2) {
        return createDbDiagramCheckBoxTree(leftComp, dbDiagram2, false);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createDbDiagramCheckBoxTree".
     * 
     * @param leftComp
     * @param dbDiagram2
     * @param isTitle
     * @return
     */
    public CheckboxTreeViewer createDbDiagramCheckBoxTree(Composite leftComp, Object dbDiagram2, boolean isTitle) {
        GridData gridData;
        CheckboxTreeViewer viewer = new ContainerCheckedTreeViewer(leftComp, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
        gridData = new GridData(GridData.FILL_BOTH);
        viewer.getTree().setLayoutData(gridData);
        ColumnsTreeProvider provider = new ColumnsTreeProvider();
        viewer.setContentProvider(provider);
        viewer.setLabelProvider(provider);
        if (isTitle) {
            List<Object> list = new ArrayList<Object>();
            list.add(dbDiagram2);
            viewer.setInput(list);
            viewer.expandToLevel(2);
        } else {
            viewer.setInput(dbDiagram2);
            viewer.expandAll();
        }

        return viewer;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com QueryUiUtils class global comment. Detailled comment <br/>
     * 
     * $Id: Dengues.epf 2007-12-15 qiang.zhang $
     * 
     */
    class ColumnsTreeProvider extends LabelProvider implements ITreeContentProvider {

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
         */
        public Object[] getChildren(Object parentElement) {
            if (parentElement instanceof DBTable) {
                return ((DBTable) parentElement).getColumns().toArray(new Object[0]);
            } else if (parentElement instanceof DatabaseDiagram) {
                DatabaseDiagram databaseDiagram = (DatabaseDiagram) parentElement;
                List tables = new ArrayList();
                EList dbChildren = databaseDiagram.getDbChildren();
                for (Object object : dbChildren) {
                    if (object instanceof DBTable) {
                        tables.add(object);
                    }
                }
                return tables.toArray(new Object[0]);
            } else if (parentElement instanceof List) {
                return ((List) parentElement).toArray(new Object[0]);
            } else if (parentElement instanceof DenguesProject) {
                DenguesProject project = (DenguesProject) parentElement;
                EList<ConnPropertySetType> connProperties = project.getProjectType().getConnProperties();
                return connProperties.toArray(new ConnPropertySetType[0]);
            }
            return new Object[0];
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
         */
        public Object getParent(Object element) {
            if (element instanceof DBTable) {
                return ((DBTable) element).getDbDiagram();
            } else if (element instanceof DBColumn) {
                return ((DBColumn) element).getTable();
            }
            return null;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
         */
        public boolean hasChildren(Object element) {
            return getChildren(element).length > 0;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
         */
        public Object[] getElements(Object inputElement) {
            return getChildren(inputElement);
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
         * java.lang.Object, java.lang.Object)
         */
        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {

        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
         */
        @Override
        public Image getImage(Object element) {
            if (element instanceof DBTable) {
                return ImageUtil.getImage(IDenguesSharedImage.VIEW_TABLE);
            } else if (element instanceof DBColumn) {
                DBColumn column = (DBColumn) element;
                if (column.isKey()) {
                    return ImageUtil.getImage(IDenguesSharedImage.TABLEVIEW_KEY);
                } else if (column.isForeignKey()) {
                    return ImageUtil.getImage(IDenguesSharedImage.VIEW_PK);
                } else {
                    return ImageUtil.getImage(IDenguesSharedImage.VIEW_COLUMN);
                }
            } else if (element instanceof DatabaseDiagram) {
                return ImageUtil.getImage(IDenguesSharedImage.VIEW_DATA);
            } else if (element instanceof DenguesProject) {
                return ImageUtil.getImage(IDenguesSharedImage.WDACTIONS_PROJECT);
            } else if (element instanceof ConnPropertySetType) {
                return ImageUtil.getImage(IDenguesSharedImage.PREFS_CONNSET);
            }

            return super.getImage(element);
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
         */
        @Override
        public String getText(Object element) {
            if (element instanceof DiagramChild) {
                DiagramChild diagramChild = ((DiagramChild) element);
                String name = diagramChild.getName();
                if (EMFDataType.SCRIPTS == diagramChild.getEmfType()) {
                    Object object = diagramChild.getProperties().get(SCRIPTS_COMMENT);
                    if (object != null) {
                        name += " [" + object.toString() + "]";
                    }
                }
                return name;
            } else if (element instanceof DatabaseDiagram) {
                Object sidName = ((DatabaseDiagram) element).getProperties().get(
                        EConnectivityProperties.PROP_ID_DATABASE.getPropId());
                return sidName == null ? "" : sidName.toString(); //$NON-NLS-1$
            } else if (element instanceof DenguesProject) {
                return ((DenguesProject) element).getName();
            } else if (element instanceof ConnPropertySetType) {
                return ((ConnPropertySetType) element).getId();
            }
            return super.getText(element);
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getFksFromFK".
     * 
     * @param foreignKey
     * @return
     */
    public static List<ForeignKey> getFksFromFK(ForeignKey foreignKey) {
        List<ForeignKey> list = new ArrayList<ForeignKey>();
        DBTable table = foreignKey.getSource().getTable();
        DBTable target = foreignKey.getTarget().getTable();
        EList columns = table.getColumns();
        for (Object object : columns) {
            DBColumn column = (DBColumn) object;
            EList outputs = column.getOutputs();
            for (Object object2 : outputs) {
                ForeignKey key = (ForeignKey) object2;
                if (key.getTarget().getTable() == target) {
                    list.add(key);
                }
            }
            outputs = column.getInputs();
            for (Object object2 : outputs) {
                ForeignKey key = (ForeignKey) object2;
                if (key.getSource().getTable() == target) {
                    list.add(key);
                }
            }
        }
        return list;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createDbDiagramTree".
     * 
     * @param dialogArea
     * @param classesToGenerate
     */
    public TreeViewer createDbDiagramTree(Composite dialogArea, HashMap<String, List<ScriptVariable>> classesToGenerate) {
        DatabaseFactory databaseFactory = DenguesModelManager.getDatabaseFactory();
        DatabaseDiagram cdd = databaseFactory.createDatabaseDiagram();
        cdd.setEmfType(EMFDataType.SCRIPTS);
        for (String key : classesToGenerate.keySet()) {
            DBTable cdt = databaseFactory.createDBTable();
            cdt.setName(key);
            cdt.setDbDiagram(cdd);
            List<ScriptVariable> cs = classesToGenerate.get(key);
            cdt.getProperties().put(SCRIPTS_COMMENT, cs.isEmpty() ? "Empty" : cs.get(0).getNodeId());
            for (ScriptVariable sv : cs) {
                DBColumn cdc = databaseFactory.createDBColumn();
                cdc.setName(sv.getName());
                cdc.getProperties().put(SCRIPTS_COMMENT, MetadataTypesManager.getJavaTypeName(sv.getTypeId()));
                cdc.setEmfType(EMFDataType.SCRIPTS);
                cdt.getColumns().add(cdc);
            }
            cdt.setEmfType(EMFDataType.SCRIPTS);
            cdd.getDbChildren().add(cdt);
        }
        return createDbDiagramTree(dialogArea, cdd);
    }

}
